package com.wolf.antlr;

import org.antlr.v4.runtime.ParserRuleContext;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

public interface IListener {
    Set<Integer> lines = new HashSet<>();
    Set<String> functionDeclaration = new HashSet<>();
    Set<Tuple<ParserRuleContext, String>> collection = new HashSet<>();

    default void search(ParserRuleContext ctx, String declaration) {
        this.searchByLine(ctx, declaration);
        this.searchByDeclaration(ctx, declaration);
    }

    default void searchByLine(ParserRuleContext ctx, String declaration) {
        if (lines.isEmpty()) {
            return;
        }
        int startLines = ctx.getStart().getLine();
        int endLines = ctx.getStop().getLine();
        List<Integer> foundLines = new ArrayList<>();
        for (Integer line : lines) {
            if (startLines <= line && line <= endLines) {
                this.collection.add(new Tuple<>(ctx, declaration));
                foundLines.add(line);
            }
        }
        for (Integer foundLine : foundLines) {
            lines.remove(foundLine);
        }
    }

    default void searchByDeclaration(ParserRuleContext ctx, String declaration) {
        if (functionDeclaration.isEmpty()) {
            return;
        }
        for (String functionDeclaration : functionDeclaration) {
            if (declaration.equals(functionDeclaration)) {
                this.collection.add(new Tuple<>(ctx, functionDeclaration));
                IListener.functionDeclaration.remove(functionDeclaration);
                break;
            }
        }
    }

    default void setLines(List<Integer> lines) {
        this.lines.clear();
        this.lines.addAll(lines);
    }

    default void setFunctionDeclaration(String functionDeclaration) {
        this.functionDeclaration.clear();
        this.functionDeclaration.add(functionDeclaration);
    }

    default List<MethodFragment> getMethodFragments() {
        List<MethodFragment> list = new ArrayList<>();
        for (Tuple<ParserRuleContext, String> context : collection) {
            ParserRuleContext ctx = context.element1();
            int startIndex = ctx.getStart().getStartIndex();
            int stopIndex = ctx.getStop().getStopIndex() + 1;
            int startLine = ctx.getStart().getLine();
            int endLine = ctx.getStop().getLine();
            String methodDeclaration = context.element2();
            MethodFragment methodFragment = new MethodFragment(startIndex, stopIndex,
                    startLine, endLine, methodDeclaration);
            list.add(methodFragment);
        }
        return list;
    }
}
